package com.herui.sdyu_lib.http.okhttp;

import com.google.gson.GsonBuilder;
import com.herui.sdyu_lib.http.annotation.BodyType;
import com.herui.sdyu_lib.http.param.RetrofitParam;
import com.herui.sdyu_lib.http.utils.Exceptions;
import com.herui.sdyu_lib.http.utils.Platform;

import java.io.IOException;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import okhttp3.Interceptor;
import okhttp3.OkHttpClient;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
import retrofit2.converter.scalars.ScalarsConverterFactory;

public class RetrofitCall {

    public static boolean isTest;
    private volatile static OkHttpClient okHttpClient;
    private volatile static Platform platform;
    private Retrofit retrofit;

    private RetrofitParam retrofitParam;

    /**
     * 默认信任所有的证书 TODO 最好加上证书认证，主流App都有自己的证书
     *
     * @return
     */
    private static SSLSocketFactory createSSLSocketFactory() {

        SSLSocketFactory sSLSocketFactory = null;

        try {
            SSLContext sc = SSLContext.getInstance("TLS");
            sc.init(null, new TrustManager[]{new TrustAllManager()}, new SecureRandom());
            sSLSocketFactory = sc.getSocketFactory();
        } catch (Exception e) {
        }

        return sSLSocketFactory;
    }

    private static class TrustAllManager implements X509TrustManager {
        @Override
        public void checkClientTrusted(X509Certificate[] chain, String authType) throws
                CertificateException {
        }

        @Override
        public void checkServerTrusted(X509Certificate[] chain, String authType)

                throws CertificateException {
        }

        @Override
        public X509Certificate[] getAcceptedIssuers() {
            X509Certificate[] x509Certificates = new X509Certificate[0];
            return x509Certificates;
        }
    }

    private static class TrustAllHostnameVerifier implements HostnameVerifier {
        @Override
        public boolean verify(String hostname, SSLSession session) {
            return true;
        }
    }

    public RetrofitCall(RetrofitParam retrofitParam) {
        this(retrofitParam, null);
    }

    public RetrofitCall(RetrofitParam retrofitParam, Interceptor interceptor) {
        this.retrofitParam = retrofitParam;
        if (okHttpClient == null) {
            synchronized (OKHttpRequestCall.class) {
                if (okHttpClient == null) {
                    OkHttpClient.Builder mBuilder = mBuilder = new OkHttpClient.Builder();
                    mBuilder.sslSocketFactory(createSSLSocketFactory());
                    mBuilder.hostnameVerifier(new TrustAllHostnameVerifier());

                    if (interceptor != null){
                        mBuilder.addInterceptor(interceptor);
                    }

                    okHttpClient = mBuilder.build();

                    platform = Platform.get();
                }
            }
        }
    }

    public <T> T conver(Class<T> monthClass) {

        BodyType bodyType = monthClass.getAnnotation(BodyType.class);
        GsonConverterFactory converterFactory = null;
        if (bodyType != null)
            converterFactory = GsonConverterFactory.create(new GsonBuilder()
                    .setDateFormat(bodyType.bodyDateFormat())
                    .create());
        else
            converterFactory = GsonConverterFactory.create();

        Retrofit retrofit = new Retrofit.Builder().baseUrl(retrofitParam.getBaseUrl())
                .addConverterFactory(ScalarsConverterFactory.create())
                .addConverterFactory(converterFactory).client(okHttpClient).build();
        return retrofit.create(monthClass);
    }

    public <T> void call(Call<T> call, final com.herui.sdyu_lib.http.callback.Callback.CommonCallback<T> callback) {
        if (isTest){
            try {
                callback.onSuccess(call(call));
            } catch (Exception e) {
                callback.onError(e, null, null);
            }
        }else{
            call.enqueue(new Callback<T>() {

                @Override
                public void onResponse(Call<T> call, Response<T> response) {
                    if (response.isSuccessful()) {
                        callback.onSuccess(response.body());
                    } else {
                        callback.onError(null, response.code() + "", response.message());
                    }
                }

                @Override
                public void onFailure(Call<T> call, Throwable t) {
                    callback.onError(t, null, null);
                }
            });
        }
    }

    public <T> T call(Call<T> call) throws Exception {
        try {
            Response<T> response = call.execute();
            if (response.isSuccessful())
                return response.body();
            else
                Exceptions.RequestException("request fail code: %d   message: %s", response.code
                        (), response.message());
        } catch (IOException e) {
            throw e;
        }

        return null;
    }

}
